/** \file RandomMT.cc
 * Definitions for the Mersenne Twister random number generator class.
 *
 * (c) Copyright Semih Cemiloglu
 * All rights reserved, see COPYRIGHT file for details.
 *
 * $Id: Random.cc 119 2006-06-21 04:57:25Z semihc $
 *
 *
 */

#include "RandomMT.hh"
#include <iostream>

using namespace std;
using namespace TC;


TC_IDENT("$Id$");


// Include non-inline function definitions
#ifndef TC_USE_INLINE
# include "RandomMT.inl"
#endif


uint32_t RandomMT::Hash(time_t t, clock_t c)
{
  // Get a uint32_t from t and c
  // Better than uint32_t(x) in case x is floating point in [0,1]
  // Based on code by Lawrence Kirby (fred@genesis.demon.co.uk)

  // guarantee time-based seeds will change
  static TC_THREAD_LOCAL uint32_t differ = 0;  
  
  uint32_t h1 = 0;
  unsigned char *p = reinterpret_cast<unsigned char *>(&t);
  for( size_t i = 0; i < sizeof(t); ++i )
  {
    h1 *= UCHAR_MAX + 2U;
    h1 += p[i];
  }
  uint32_t h2 = 0;
  p = reinterpret_cast<unsigned char *>(&c);
  for( size_t j = 0; j < sizeof(c); ++j )
  {
    h2 *= UCHAR_MAX + 2U;
    h2 += p[j];
  }
  return ( h1 + differ++ ) ^ h2;
}


namespace TC {

ostream& operator<<(ostream& os, const RandomMT& mtrand)
{
  register const uint32_t *s = mtrand.m_state;
  register int i = mtrand.N;
  for( ; i--; os << *s++ << "\t" ) {}
  return os << mtrand.m_left;
}

istream& operator>>(istream& is, RandomMT& mtrand)
{
  register uint32_t *s = mtrand.m_state;
  register int i = mtrand.N;
  for( ; i--; is >> *s++ ) {}
  is >> mtrand.m_left;
  mtrand.m_next = &mtrand.m_state[mtrand.N-mtrand.m_left];
  return is;
}

}


